package chapter_6.demo1;

import chapter_4.Dish;
import chapter_6.CaloricLevel;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;

/**
 * @author: hero生仔
 */
public class Solution {
    static List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH));

    public static void main(String[] args) {
        extracted01();

        extracted02();

        extracted03();

        extracted04();
    }

    private static void extracted04() {
    /*
    你可能想把热量不到400卡路里的菜划分为“低热量”（diet），热量400到700
    卡路里的菜划为“普通”（normal），高于700卡路里的划为“高热量”（fat）。
    可以自定义枚举类,然后在 groupingBy 方法中进行语句判断
     */
        Map<CaloricLevel, List<Dish>> map = menu.stream()
                .collect(groupingBy(dish -> {
                    if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                    else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                    else return CaloricLevel.FAT;
                }));
        System.out.println(map);
    }

    private static void extracted03() {
        // 要把菜单中的菜按照类型进行分类,有肉的放一组,有鱼的放一组,其他的都放另一组
        Map<Dish.Type, List<Dish>> map = menu.stream()
                .collect(groupingBy(Dish::getType));
        System.out.println(map);
    }

    private static void extracted02() {
    /*
    广义规约汇总
    它需要三个参数:
    第一个参数是归约操作的起始值，也是流中没有元素时的返回值，所以很显然对于数值和而言0是一个合适的值。
    第二个参数就是将菜肴转换成一个表示其所含热量的int。
    第三个参数是一个BinaryOperator，将两个项目累积成一个同类型的值。
     */
        int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));
    }

    private static void extracted01() {
        // 连接字符串
        String result = menu.stream()
                .map(Dish::getName)
                .collect(Collectors.joining());
        System.out.println(result);

        // 但该字符串的可读性并不好。幸好，joining工厂方法有一个重载版本可以接受元素之间的
        //分界符，这样你就可以得到一个逗号分隔的菜肴名称列表：
        String ans = menu.stream()
                .map(Dish::getName)
                .collect(Collectors.joining(","));
        System.out.println(ans);
    }
}
